{
  // 将一个字符串字面量类型的 'typescript' 转为首字母大写的 'Typescript'

  // Uppercase 为ts内置类型，将string类型转为大写

  type CapitalizeStr<Str extends string> = Str extends `${infer First}${infer Rest}`
    ? `${Uppercase<First>}${Rest}`
    : Str;

  type res = CapitalizeStr<'typescript'>; // type res = "Typescript"
}

{
  // 实现 dong_dong_dong 到 dongDongDong 的变换

  type CameCase<Str extends string> = Str extends `${infer Left}_${infer Right}${infer Rest}`
    ? `${Left}${Uppercase<Right>}${CameCase<Rest>}`
    : Str;

  type res = CameCase<'dong_dong_dong'>;

  /**
   * 类型参数 Str 是待处理的字符串类型，约束为 string。
   *
   * 提取 _ 之前和之后的两个字符到 infer 声明的局部变量 Left 和 Right，剩下的字符放到 Rest 里。
   *
   * 然后把右边的字符 Right 大写，和 Left 构造成新的字符串，剩余的字符 Rest 要继续递归的处理。
   *
   * 这样就完成了从下划线到驼峰形式的转换：
   */
}

{
  // 删除字符串中的某个子串

  type DropSubStr<
    Str extends string,
    SubStr extends string,
  > = Str extends `${infer Prefix}${SubStr}${infer Suffix}`
    ? DropSubStr<`${Prefix}${Suffix}`, SubStr>
    : Str;

  type res = DropSubStr<'dong~~~', '~'>;

  /**
   * 类型参数 Str 是待处理的字符串， SubStr 是要删除的字符串，都通过 extends 约束为 string 类型。
   *
   * 通过模式匹配提取 SubStr 之前和之后的字符串到 infer 声明的局部变量 Prefix、Suffix 中。
   *
   * 如果不匹配就直接返回 Str。
   *
   * 如果匹配，那就用 Prefix、Suffix 构造成新的字符串，然后继续递归删除 SubStr。直到不再匹配，也就是没有 SubStr 了。
   */
}

export {};
